home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DS-CD ROM 2 1993 August
/
DS CD-ROM 2.Ausgabe (August 1993).iso
/
programm
/
ds0334
/
sim51_04.arj
/
BEF51.DOC
< prev
next >
Wrap
Text File
|
1993-01-03
|
39KB
|
1,179 lines
Befehlssatz der 8051 Mikrocontroller:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dieser Text enthält eine Aufstellung aller Maschinenbefehle des
8051. Alle Weiterentwicklungen besitzen denselben Befehlssatz. Sie
unterscheiden sich nur in erweiterten Funktionen, die werden aber
über zusätzliche Spezial-Funktion-Register (SFR) gesteuert.
Opcodes:
~~~~~~~~
Die Maschinenbefehle werden im Programmspeicher als Zahlenwerte ab-
gelegt.
┌──────────┬───────────┬───────────┐
│ OpCode │ 1.Operant │ 2.Operant │
└──────────┴───────────┴───────────┘
Für den Operations-Code sind Werte von 0 bis 255 zulässig. Damit
können bis zu 256 Befehle unterschieden werden. Die Operanten sind
optional. Somit belegt ein Befehl 1 bis 3 Byte im Speicher.
Cyclen:
~~~~~~~
Die CPU's der 8051-Reihe können mit 1,2...12 MHz (neue Typen auch
bis 20 MHz) getacktet werden.
Quarz-Takt: ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌
─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘
System-Takt: | S1 | S2 | S3 | S4 | S5 | S6 | S1
|<------------------ 1. Cyclus ---------------->|<---
| ^Code-Fetch ^Code-Fetch
Der Code-Fetch (für OpCode) eines abzuarbeitenden Befehls erfolgt
in S1. In S4 wird der 1.Operant gelesen. Bei Befehlen ohne Operan-
ten wird der Wert wieder verworfen. In S5/S6 wird der Befehl aus-
geführt, der Cyclus ist beendet. Nun gibt es auch Befehle mit zwei
Operanten oder die mehr Zeit zur Ausführung benötigen. Sie benö-
tigen dann 2 oder 4 Cycluse.
Je Cyclus erfolgen immer zwei Code-Fechtes (außer bei MOVX). Zu-
viel gelesener Code wird wieder verworfen, indem der PC (Programm
Counter) nicht erhöht wird.
Mnemonics:
~~~~~~~~~~
Die Zahlencodes für die Befehle werden üblich mit einem Assembler
generiert. Der Programmierer hat so nicht nicht mit Zahlen zu jon-
glieren, sondern kann die Befehle in Worten (Mnemonics) hinschrei-
ben, die dann vom Assembler übersetzt werden.
Im folgenden werden die 8051-Befehle beschrieben, es werden Opcode
und Mnemonics, die benötigte Cycluse und die sich ändernden Flags
angegeben. Weitere Ausführungen zur 8051-Hardware und zu den ver-
wendeten Abkürzungen finden sich am Ende dises Textes.
──────────────────────────────────────────────────────────────────
ACALL Flags: -
Absolute CALL (innerhalb 2 KByte Page):
Der PC (Programm-Counter) wird um 2 incrementiert und die Return-
Adresse auf den Stack gelegt (low Byte zuerst). Für den Einsprung
ins Unterprogramm. wird die Adresse folgendermaßen gebildet:
A11 bis A15 im PC (Programm-Counter) bleiben unverändert,
die unteren 11 Bit werden aus dem Opcode geladen.
┌────────────────┬───────────────────────┐
ACALL codeAdr │A10 A9 A8 1 0001│A7 A6 A5 A4 A3 A2 A1 A0│ 2 Cyc
└────────────────┴───────────────────────┘
──────────────────────────────────────────────────────────────────
ADD Flags: CY AC P OV
Addiere zu ACC
Addiere Wert, Register-Inhalt oder intern RAM-Inhalt zum ACC.
Nach der Ausführung hält der ACC das Ergebnis, CY hält den Über-
trag aus Bit 7 und AC hält den Übertrag aus Bit 3. Das OV-Flag ist
gesetzt, wenn ein Vorzeichenfehler auftrat.
┌─────────┬─────────┐
ADD A, #wert │ 24h │ wert │ 1 Cyc
├─────────┼─────────┘
ADD A, @Ri │0010 011i│ 1 Cyc
├─────────┤
ADD A, Rn │0010 1nnn│ 1 Cyc
├─────────┼─────────┐
ADD A, data │ 25h │ data │ 1 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
ADDC Flags: CY AC P OV
Addiere mit Übertrag zu ACC
Addiere Wert, Register-Inhalt, oder intern RAM-Inhalt und CY zum
ACC. Nach der Ausführung hält der ACC das Ergebnis, CY hält den
Übertrag aus Bit 7 und AC hält den Übertrag aus Bit 3. Das OV-Flag
ist gesetzt, wenn ein Vorzeichenfehler auftrat.
┌─────────┬─────────┐
ADDC A, #wert │ 34h │ wert │ 1 Cyc
├─────────┼─────────┘
ADDC A, @Ri │0011 011i│ 1 Cyc
├─────────┤
ADDC A, Rn │0011 1nnn│ 1 Cyc
├─────────┼─────────┐
ADDC A, data │ 35h │ data │ 1 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
AJMP Flags: -
Absoluter Sprung (innerhalb 2 KByte Page):
Der PC wird um 2 incrementiert, die Zieladresse wird dann folgen-
dermaße gebildet:
A11 bis A15 im PC (Programm-Counter) bleiben unverändert,
die unteren 11 Bit werden aus dem Opcode geladen.
┌────────────────┬───────────────────────┐
AJMP codeAdr │A10 A9 A8 0 0001│A7 A6 A5 A4 A3 A2 A1 A0│ 2 Cyc
└────────────────┴───────────────────────┘
──────────────────────────────────────────────────────────────────
ANL Flags: -
Logisch AND zu ACC, intern RAM oder SFR
Der Inhalt der angegebenen Register wird bitweise logisch AND ver-
knüpft und im ersten Register gespeichert.
┌─────────┬─────────┐
ANL A, #wert │ 54h │ wert │ 1 Cyc P-Flag
├─────────┼─────────┘
ANL A, @Ri │0101 011i│ 1 Cyc P-Flag
├─────────┤
ANL A, Rn │0101 1nnn│ 1 Cyc P-Flag
├─────────┼─────────┐
ANL A, data │ 55h │ data │ 1 Cyc P-Flag
├─────────┼─────────┤
ANL data, A │ 52h │ data │ 1 Cyc
├─────────┼─────────┼─────────┐
ANL data, #wert │ 53h │ data │ wert │ 2 Cyc
└─────────┴─────────┴─────────┘
(Anmerkung: X AND Y = 1 nur dann, wenn beide X=1 und Y=1)
──────────────────────────────────────────────────────────────────
ANL Flags: CY
Logisch AND zum CY-Flag
Der Inhalt der angegebenen Bit-Adresse wird logisch AND mit dem CY-
Flag verknüpft. /bit bedeutet, das der negierte Bit-Inhalt verwen-
det wird.
┌─────────┬─────────┐
ANL C, bit │ 82h │ bitAdr │ 2 Cyc
├─────────┼─────────┤
ANL C, /bit │ B0h │ bitAdr │ 2 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
CJNE Flags: CY
Vergleiche und springe, wenn nicht gleich
Ist der linke Operand kleiner als der Rechte, so ist anschließend
das Carry Flag gesetzt (CY = 1).
┌─────────┬─────────┬─────────┐
CJNE A, data, codeAdr │ B5h │ data │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┤
CJNE A, #wert, codeAdr │ B4h │ wert │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┤
CJNE Rn, #wert, codeAdr │1011 1nnn│ wert │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┤
CJNE @Ri, #wert, codeAdr │1011 011i│ wert │ Offset │ 2 Cyc
└─────────┴─────────┴─────────┘
──────────────────────────────────────────────────────────────────
CLR Flags: P
Lösche ACC
┌─────────┐
CLR A │ E4h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
CLR Flags: CY
Lösche Bit
┌─────────┐
CLR C │ C3h │ 1 Cyc
├─────────┼─────────┐
CLR bit │ C2h │ bitAdr │ 1 Cyc no Flags
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
CPL Flags: P
Einerkomplement zu ACC (= ACC bitweise invertieren)
Der Befehlssatz des 8051 kennt kein Zweierkomlement. Es kann aber
gebildet werden durch CPL A mit anschließenden INC A.
┌─────────┐
CPL A │ F4h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
CPL Flags: CY
Invertiere Bit
┌─────────┐
CPL C │ B3h │ 1 Cyc
├─────────┼─────────┐
CPL bit │ B2h │ bitAdr │ 1 Cyc no Flags
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
DA Flags: CY P
Decimal Adjust von ACC nach BCD-Addition
Wurden zwei BCD Zahlen miteinander addiert, so muß danach das Er-
gebnis korrigiert werden, soll es auch im BCD-Format erscheinen.
Ist das AC-Flag gesetzt, oder das low Nibble > 9, dann wird 6 ad-
diert. Ist das C-Flag gesetzt, oder das high Nibble > 9, dann wird
60h addiert. Wenn beim Ergebnis ein Übertrag von Bit 7 des ACC er-
folgt, wird das Carry-Flag (C=1) gesetzt.
┌─────────┐
DA A │ D4h │ 1 Cyc
└─────────┘
Beispiel: bcd_59 = 0101 1001
bcd_68 = 0110 1000
+ ────────────
nach ADD: 1100 0001 (Flags: AC=1, CY=0)
wegen (AC=1): 0000 0110
wegen (high Nibble>9): 0110 0000
+ ────────────
BCD-Ergebnis: bcd_27 = 0010 0111 (Flags: CY=1)
Das richtige Ergebnis wäre 59 + 68 = 127. Hier ist aber ein Über-
lauf, daher nur 27 und das CY-Flag ist gesetzt.
──────────────────────────────────────────────────────────────────
DEC Flags: -
Decrement
Der Inhalt der angegebenen Register wird um 1 erniedrigt.
┌─────────┐
DEC A │ 14h │ 1 Cyc P-Flag
├─────────┤
DEC Rn │0001 1nnn│ 1 Cyc
├─────────┤
DEC @Ri │0001 011i│ 1 Cyc
├─────────┼─────────┐
DEC data │ 15h │ data │ 1 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
DIV Flags: CY P OV
Dividiere Akku durch B-Register
Das Ergebnis steht im ACC und der Rest in B. Bei einem Fehler (Di-
vision durch 0) ist das OV-Flag gesetzt. Das Carry Flag wird immer
gelöscht.
┌─────────┐
DIV AB │ 84h │ 4 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
DJNZ Flags: -
Decrementiere den Inhalt des angegeben Registers und springe, wenn
nicht 0.
┌─────────┬─────────┐
DJNZ Rn, codeAdr │1101 1nnn│ Offset │ 2 Cyc
├─────────┼─────────┼─────────┐
DJNZ data, codeAdr │ D5h │ data │ Offset │ 2 Cyc
└─────────┴─────────┴─────────┘
──────────────────────────────────────────────────────────────────
INC Flags: -
Increment
Der Inhalt der angegebenen Register wird um 1 erhöht.
┌─────────┐
INC A │ 04h │ 1 Cyc P-Flag
├─────────┤
INC Rn │0000 1nnn│ 1 Cyc
├─────────┤
INC @Ri │0000 011i│ 1 Cyc
├─────────┼─────────┐
INC data │ 05h │ data │ 1 Cyc
├─────────┼─────────┘
INC DPTR │ A3h │ 2 Cyc *16-Bit-Befehl
└─────────┘
──────────────────────────────────────────────────────────────────
J? = Bedingter Sprung Flags: -
Sprung, wenn die Bedingung erfüllt ist. Für die Zieladresse wird
der PC erhöht, dann wird der vorzeichenbehaftete Offset addiert.
JZ --> springe, wenn ACC = 0
JNZ --> springe, wenn ACC nicht 0
JC --> springe, wenn CY = 1
JNC --> springe, wenn CY = 0
JB --> springe, wenn Bit = 1
JNB --> springe, wenn Bit = 0
JBC --> springe, wenn Bit = 1 und lösche Bit
┌─────────┬─────────┐
JZ codeAdr │ 60h │ Offset │ 2 Cyc
├─────────┼─────────┤
JNZ codeAdr │ 70h │ Offset │ 2 Cyc
├─────────┼─────────┤
JC codeAdr │ 40h │ Offset │ 2 Cyc
├─────────┼─────────┤
JNC codeAdr │ 50h │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┐
JB bit, codeAdr │ 20h │ bitAdr │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┤
JNB bit, codeAdr │ 30h │ bitAdr │ Offset │ 2 Cyc
├─────────┼─────────┼─────────┤
JBC bit, codeAdr │ 10h │ bitAdr │ Offset │ 2 Cyc
└─────────┴─────────┴─────────┘
──────────────────────────────────────────────────────────────────
JMP Flags: -
Springe indirekt
Der Programm Counter (PC) wird mit der Summe aus ACC und DPTR ge-
laden (= Sprung zu dieser Adresse).
┌─────────┐
JMP @A+DPTR │ 73h │ 2 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
LCALL Flags: -
Long CALL
Der PC (Programm Counter) wird um 3 incrementiert und die Return-
Adresse auf den Stack gelegt (low Byte zuerst). Dann erfolgt der
Sprung an die angegebene Adresse.
┌─────────┬────────────┬───────────┐
LCALL codeAdr │ 12h │HIGH(codAdr)│LOW(codAdr)│ 2 Cyc
└─────────┴────────────┴───────────┘
──────────────────────────────────────────────────────────────────
LJMP Flags: -
Long JUMP
Sprung zur im Opcode angegebenen Adresse.
┌─────────┬────────────┬───────────┐
LJMP codeAdr │ 02h │HIGH(codAdr)│LOW(codAdr)│ 2 Cyc
└─────────┴────────────┴───────────┘
──────────────────────────────────────────────────────────────────
MOV Flags: -
Schreibe/Kopiere in ACC, internes RAM oder SFR
Jeweils der in der Mnemonic rechts stehende Operand wird in den
Linken geschrieben. Bemerkenswert ist, daß bei "MOV data1, data2"
die Reihenfolge im Hexcode gegenüber der im Memomic vertauscht ist.
┌─────────┐
MOV A, Rn │1110 1nnn│ 1 Cyc P-Flag
├─────────┤
MOV A, @Ri │1110 011i│ 1 Cyc P-Flag
├─────────┼─────────┐
MOV A, data │ E5h │ data │ 1 Cyc P-Flag
├─────────┼─────────┤
MOV A, #wert │ 74h │ wert │ 1 Cyc P-Flag
└─────────┴─────────┘
┌─────────┐
MOV Rn, A │1111 1nnn│ 1 Cyc
├─────────┼──────────┐
MOV Rn, data │1010 1nnn│ data │ 2 Cyc
├─────────┼──────────┤
MOV Rn, #wert │0111 1nnn│ wert │ 1 Cyc
├─────────┼──────────┘
MOV @Ri, A │1111 011i│ 1 Cyc
├─────────┼──────────┐
MOV @Ri, data │1010 011i│ data │ 2 Cyc
├─────────┼──────────┤
MOV @Ri, #wert │0111 011i│ wert │ 1 Cyc
├─────────┼──────────┤
MOV data, A │ F5h │ data │ 1 Cyc
├─────────┼──────────┤
MOV data, Rn │1000 1nnn│ data │ 2 Cyc
├─────────┼──────────┤
MOV data, @Ri │1000 011i│ data │ 2 Cyc
├─────────┼──────────┼─────────┐
MOV data, #wert │ 75h │ data │ wert │ 2 Cyc
├─────────┼──────────┼─────────┤
MOV data1, data2 │ 85h │ data2 │ data1 │ 2 Cyc
├─────────┼──────────┼─────────┤
MOV DPTR, #wert │ 90h │HIGH(wert)│LOW(wert)│ 2 Cyc *16-Bit
└─────────┴──────────┴─────────┘
──────────────────────────────────────────────────────────────────
MOV Flags: -
Kopiere Bit
Kopiere Inhalt aus Bit-Adresse in C bzw. C in Bit-Adresse.
┌─────────┬─────────┐
MOV C, bit │ A2h │ bitAdr │ 1 Cyc CY-Flag
├─────────┼─────────┤
MOV bit, C │ 92h │ bitAdr │ 2 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
MOVC Flags: P
Lese Code-Byte
Ein Byte aus dem Programmspeicher wird in den ACC gelesen. Die
Adresse wird aus der Summe der Inhalte vom ACC und dem DPTR bzw.
dem (zuvor um 1 erhöhten) Programm-Counter gebildet. Der Zugriff
erfolgt anstelle des ersten Code-Fetch im zweiten Cyclus.
Mit MOVC können beispielsweise Tabellen im EPROM gelesen werden.
┌─────────┐
MOVC A, @A+DPTR │ 93h │ 2 Cyc
├─────────┤
MOVC A, @A+PC │ 83h │ 2 Cyc
└─────────┘
Beachte: Beim externen Programmspeicherzugriff wird die Code-Adres-
se multipexed an den Pins von Port P0 und P2 ausgegeben. Automa-
tisch schreibt die CPU #0FFh in das Latch von P0! Der Inhalt
von P2 ändert sich nicht.
──────────────────────────────────────────────────────────────────
MOVX Flags: -
externer Daten-Speicher-Zugriff
Der Zugriff auf den externen Datenspeicher erfolgt anstelle der
beiden Code-Fetch im zweiten Cyclus. Beim Zugriff @DPTR wird die
XDATA-Adresse multiplexed an den Pins von Port P0 und P2 ausgege-
ben. Beim Zugriff @Ri liegt der Inhalt des P2-Latches während des
Zugriffs an den P2-Pins, der Inhalt von Ri wird multiplexed an den
P0-Pins ausgegeben. Hier hat der Anwender vor dem Zugriff selbst
das High-Byte der Adresse in P2 zu schreiben.
┌─────────┐
MOVX A, @DPTR │ E0h │ 2 Cyc P-Flag
├─────────┤
MOVX @DPTR, A │ F0h │ 2 Cyc
├─────────┤
MOVX A, @Ri │1110 001i│ 2 Cyc P-Flag
├─────────┤
MOVX @Ri, A │1111 001i│ 2 Cyc
└─────────┘
Beachte: Das P0-Latch wird von der CPU-Hardware vor dem Zugriff
mit #0FFh überschrieben, der Inhalt des P2-Latch bleibt jedoch
erhalten. Der Inhalt des P2-Latches kann nicht zurückgelesen
werden. Ein Lesezugriff erfolgt von den Pins, nicht vom Latch.
Bei externen Code-Fetch können sogar die Pins nicht gelesen wer-
den, man bekäme nur immer die letzte High-Code-Adresse.
──────────────────────────────────────────────────────────────────
MUL Flags: CY P OV
Multipiziere Akku mit B-Register:
Das Ergebnis steht in ACC. Wenn das Ergebnis größer als 8 Bit ist,
steht das low Byte in ACC, das High Byte in B und das OV-Flag ist
gesetzt. Das CY-Flag wird immer gelöscht.
┌─────────┐
MUL AB │ A4h │ 4 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
NOP Flags: -
No Operation.
NOP ist oft dienlich, wenn eine Wartezeit benötigt wird. Bei einem
Takt von 12 MHz dauert ein NOP 1 µs.
┌─────────┐
NOP │ 00h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
ORL Flags: -
Logisch OR zu ACC, intern RAM oder SFR
Der Inhalt der angegebenen Register wird bitweise logisch OR ver-
knüpft und im ersten Register gespeichert.
┌─────────┬─────────┐
ORL A, #wert │ 44h │ wert │ 1 Cyc P-Flag
├─────────┼─────────┘
ORL A, @Ri │0100 011i│ 1 Cyc P-Flag
├─────────┤
ORL A, Rn │0100 1nnn│ 1 Cyc P-Flag
├─────────┼─────────┐
ORL A, data │ 45h │ data │ 1 Cyc P-Flag
├─────────┼─────────┤
ORL data, A │ 42h │ data │ 1 Cyc
├─────────┼─────────┼─────────┐
ORL data, #wert │ 43h │ data │ wert │ 2 Cyc
└─────────┴─────────┴─────────┘
(Anmerkung: X OR Y = 1 dann, wenn auch nur eines X=1 oder Y=1)
──────────────────────────────────────────────────────────────────
ORL Flags: CY
Logisch OR zum CY-Flag
Der Inhalt der angegebenen Bit-Adresse wird logisch OR mit dem CY-
Flag verknüpft. /bit bedeutet, das der negierte Bit-Inhalt verwen-
det wird.
┌─────────┬─────────┐
ORL C, bit │ 72h │ bitAdr │ 2 Cyc
├─────────┼─────────┤
ORL C, /bit │ A0h │ bitAdr │ 2 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
POP Flags: -
Byte vom Stack holen
Beim POP wird das BYTE @SP gelesen und in die angegebene intern
RAM- bzw. SFR-Adresse geschrieben, dann wird der SP decrementiert.
Siehe auch PUSH, RET, RETI, Calls und die Bemerkungen zum Stack am
Ende des Textes.
gleich:
┌─────────┬─────────┐ MOV data, @SP
POP data │ D0h │ data │ 2 Cyc DEC SP
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
PUSH Flags: -
Byte auf Stack schieben
Beim PUSH wird der SP um incrementiert und dann der Inhalt der an-
gegebenen intern RAM- bzw. SFR-Adresse in @SP geschrieben. Der SP
zeigt immer auf das zuletzt gepushte Byte.
Ist der Stack voll (SP zeigt auf Adressen oberhalb 7Fh beim 8051),
so wird trotzdem bei einem PUSH der SP incrementiert, die Daten
gehen aber verloren.
gleich:
┌─────────┬─────────┐ INC SP
PUSH data │ C0h │ data │ 2 Cyc MOV @SP, data
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
RET Flags: -
Return von Unterprogramm:
Bei einem LCALL oder ACALL wurde die Return-Adresse auf dem Stack
abgelegt. Mit RET wird sie wieder zurück in den Programm Counter
geladen, was einem Sprung dorthin gleichkommt. Man beachte, das
eine Code-Adresse 2 Byte auf dem Stack belegt. Zuerst wurde das
Low Byte gepushed, dann das High Byte. In umgekehrter Reihenfolge
werden sie wieder gepoped.
gleich:
┌─────────┐ MOV HIGH(PC), @SP
RET │ 22h │ 2 Cyc DEC SP
└─────────┘ MOV LOW(PC), @SP
DEC SP
──────────────────────────────────────────────────────────────────
RETI Flags: -
Return von Interrupt:
Die Adresse wird in gleicher Weise vom Stack geholt, wie bei RET.
Jedoch gibt es noch eine Besonderheit: Beim 8051 gibt es 2 Prio-
ritätsstufen für Interrupts (beim 80517 auch mehr). Ist ein Inter-
rupt in Bearbeitung, sind alle Interrupts mit gleicher oder nieder-
er Priorität gesperrt. RETI gibt die höchste aktive Prioritäts-
Stufe wieder frei.
┌─────────┐
RETI │ 32h │ 2 Cyc
└─────────┘
Bemerkung: Soll aus einer Interrupt- CLR A
Routine heraus ein Software-Reset er- PUSH ACC
folgen, so darf kein LJMP 0000, son- PUSH ACC
dern nur eine Routine wie nebensteh- ACALL retiReset
end verwendet werden. retiReset:
RETI
──────────────────────────────────────────────────────────────────
RL Flags: -
Rotate ACC bitweise nach links
Schiebt den Inhalt vom ACC bitweise nach links. Das höchste Bit
wird dabei in das niedrigste geschrieben. Das Parity-Flag ändert
sich nicht, da die Summe über alle Bit's gleich bleibt.
┌─────────┐
RL A │ 23h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
RLC Flags: CY P
Rotate ACC bitweise nach links durch Carry
Schiebt den Inhalt vom ACC bitweise nach links. Das höchste Bit
wird dabei ins CY-Flag und der vorige Inhalt des CY-Flag ins nie-
drigste Bit vom ACC geschrieben.
┌─────────┐
RLC A │ 33h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
RR Flags: -
Rotate ACC bitweise nach rechts
Schiebt den Inhalt vom ACC bitweise nach rechts. Das niederste Bit
wird dabei in das höchste geschrieben. Das Parity-Flag ändert sich
nicht, da die Summe über alle Bit's gleich bleibt.
┌─────────┐
RR A │ 03h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
RRC Flags: CY P
Rotate ACC bitweise nach rechts durch Carry
Schiebt den Inhalt vom ACC bitweise nach rechts. Das niederste Bit
wird dabei in das CY_Flag und der vorige Inhalt des CY-Flag in das
höchste Bit vom ACC geschrieben.
┌─────────┐
RRC C │ 13h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
SETB Flags: -
Setze den Inhalt der angegebenen Bit-Adresse auf 1.
┌─────────┐
SETB C │ D3h │ 1 Cyc CY-Flag
├─────────┼─────────┐
SETB bit │ D2h │ bitAdr │ 1 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
SJMP Flags: -
Short Jump um Offset -128..+127
Der Programm Counter wird um 2 incrementiert und dazu wird der
Offset addiert. Der im Code eingetragene Offset ist ein vorzeichen-
behaftetes Byte. Vor der Addition erfolgt eine Byte-->Word Konver-
tierung. (Anmerkung: Der Assembler-Programmierer braucht nicht mit
Offsets rumzujonglieren, er schreibt das Label an, den Offset be-
rechnet der Assembler).
┌─────────┬─────────┐
SJMP codeAdr │ 80h │ Offset │ 2 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
SUBB Flags: CY AC P OV
Subtrahiere vom Akku mit Übertrag
Subtrahiere Wert, Register-Inhalt, oder intern RAM-Inhalt und CY
vom ACC. Nach der Ausführung hält der ACC das Ergebnis, CY hält
den Übertrag aus Bit 7 und AC hält den Übertrag aus Bit 3. Das OV-
Flag ist gesetzt, wenn ein Vorzeichenfehler auftrat.
┌─────────┬─────────┐
SUBB A, #wert │ 94h │ wert │ 1 Cyc
├─────────┼─────────┘
SUBB A, @Ri │1001 011i│ 1 Cyc
├─────────┤
SUBB A, Rn │1001 1nnn│ 1 Cyc
├─────────┼─────────┐
SUBB A, data │ 95h │ data │ 1 Cyc
└─────────┴─────────┘
──────────────────────────────────────────────────────────────────
SWAP Flags: -
Vertausche in ACC low Nibble (untere 4 Bits) mit high Nibble.
┌─────────┐
SWAP A │ C4h │ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
XCH Flags: P
Tausche ACC-Inhalt mit intern RAM- bzw. SFR-Inhalt.
┌─────────┐
XCH A, Rn │1100 1nnn│ 1 Cyc
├─────────┼─────────┐
XCH A, data │ C5h │ data │ 1 Cyc
├─────────┼─────────┘
XCH A, @Ri │1100 011i│ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
XCHD Flags: P
Tausche das Low-Nibble des adressierten Byte im internen RAM mit
dem Low_Nibble des ACC.
┌─────────┐
XCHD A, @Ri │1101 011i│ 1 Cyc
└─────────┘
──────────────────────────────────────────────────────────────────
XRL Flags: -
Logisch XOR zu ACC, intern RAM oder SFR
Der Inhalt der angegebenen Register wird bitweise logisch EXCLUSIV-
OR verknüpft und im ersten Register gespeichert.
(Anmerkung: X XOR Y = 1 dann, wenn X und Y verschieden)
┌─────────┬─────────┐
XRL A, #wert │ 64h │ wert │ 1 Cyc P-Flag
├─────────┼─────────┘
XRL A, @Ri │0110 011i│ 1 Cyc P-Flag
├─────────┤
XRL A, Rn │0110 1nnn│ 1 Cyc P-Flag
├─────────┼─────────┐
XRL A, data │ 65h │ data │ 1 Cyc P-Flag
├─────────┼─────────┤
XRL data, A │ 62h │ data │ 1 Cyc
├─────────┼─────────┼─────────┐
XRL data, #wert │ 63h │ data │ wert │ 2 Cyc
└─────────┴─────────┴─────────┘
──────────────────────────────────────────────────────────────────
??? Flags: ??
Es gibt einen OpCode beim 8051, der nicht belegt ist (reserved).
┌─────────┐
│ A5h │ ? Cyc
└─────────┘
Pseudo-Befehle:
~~~~~~~~~~~~~~~
Neben den Maschinenbefehlen definieren die Assemblersprachen wei-
tere Mnemonics, um beispielsweise Tabellen zu erstellen:
──────────────────────────────────────────────────────────────────
DB, DW Flags: -
Define Byte / Word
Die hinter DB oder DW folgenden Werte werden direkt in den Code ge-
schrieben. Bei DW wird das low Byte zuerst abgelegt! Beispiele:
DB 22h ; 22h wird in den Code geschrieben
DB 'A' ; 'A' = 41h wird in den Code geschrieben
DB 13,10,0 ; nacheinander 0Dh,0Ah,00h schreiben
DB 'Hallo' ; nacheinander die ASCII-Codes des Strings
DW 1234h ; in Code: 34h, 12h
──────────────────────────────────────────────────────────────────
CALL Flags: -
Der Assembler setzt hier selbst einen ACALL oder LCALL ein. Ist
die Zieladresse dem Assembler noch nicht bekannt (steht sie weiter
unten im Code), so setzt er immer einen LCALL, sonst wenn möglich
einen ACALL.
CALL codeAdr ---> ACALL oder LCALL
──────────────────────────────────────────────────────────────────
JMP Flags: -
Der Assembler setzt hier selbst einen SJMP, AJMP oder LJMP ein.
Ist die Zieladresse dem Assembler noch nicht bekannt (steht sie
weiter unten im Code), so setzt er immer einen LJMP, sonst wenn
möglich einen SJMP oder AJMP ein.
JMP codeAdr ---> SJMP, AJMP oder LJMP
Adress-Bereiche:
~~~~~~~~~~~~~~~~
Der 8051 besitzt ein internes RAM von 128 Byte, 256 Byte beim 8052.
Für den Zugriff gibt es mehrere Möglichkeiten: MOV, ANL, ORL, XRL,
INC, DEC, XCH.
Extern kann ein zusätzliches RAM bis 64 kByte angeschlossen werden.
Der Zugriff erfolgt über einen speziellen Befehl (MOVX). Weiters
kann extern ein Programmspeicher (EPROM) mit auch maximal 64 kByte
angeschlossen werden. Aus dem Programmspeicher wird automatisch
bei jedem Code-Fetch von der CPU-Hardware gelesen. Über den Befehl
MOVC kann auch per Software aus dem Programmspeicher gelesen wer-
den. Der gültige Adressbereich hängt von der Beschaltung der je-
weiligen Rechnerkarte ab.
Für externe Zugriffe sind also spezielle Befehle vorgesehen. Bei
internen Zuriffen wird unterschieden zwischen direkter und indi-
rekter Adressierung. Der Zugriff auf die SFR erfolgt wie auf eine
interne Speicherstelle.
internes Adressbereich für
RAM ┌────────────┐FF Spezial- ┌────────────┐FF
│ │ Funktion-│ │
│ nur │ Register │ nur │
│ indirekt │ │ direkt │
│adressierbar│ │adressierbar│
│ │ │ │
└────────────┘80 └────────────┘80
┌────────────┐7F
│ │
│ direkt und │ Zugriff auf unterschiedliche Spei-
│ indirekt │ cherbereich bei direkter und indi-
│adressierbar│ rekter Adressierung.
│ │
└────────────┘00
Neben einem direkten und indirekten Byte-Zugriff gibt es die Mög-
lichkeit bei ausgewählten Speicherstellen einzelne Bits zu manipu-
lieren. Die intern DATA Adressen (internes RAM) 20h bis 2Fh können
so auch mit den BIT Adressen 00h bis 7Fh angesprochen werden. Die
Bit Adressen 80h bis 87h wirken auf das SFR mit der DATA Adresse
80h (P0), BIT 88h bis 8Fh auf DATA 88h, usw. Somit sind einige SFR
bitweise adressierbar.
Zu einigen SFR und internen DATA Adressen gibt es speziell für sie
geltende Befehle. Diese Befehle besitzen einen kürzeren Opcode und
erlauben einen schnelleren Zugriff.
ACC = Rechenregister (Akkumulator)
R0..R7 = spezielle Speicherstellen im internen RAM, die als
Register dienen. Auswahl über Wert im PSW:
R0..R7 = [00..07], [08..0F], [10..17] oder [18..1F]
CY-Flag = Carry-Flag (liegt im PSW)
Die SFR steuern spezielle Hardwarefunktionen wie Timer und seriel-
le Schnittstelle. Das interne RAM wirkt nur als Speicher. Es hat
aber einige Besonderheiten:
* die ersten 128 Byte sind direkt adressierbar DATA 00..7Fh
* das gesamte interne RAM (bis 256 Byte beim 8052) sind indi-
rekt adressierbar IDATA 00..7Fh
* die Adressen 20h bis 2Fh sind bitweise adressierbar
BIT 00..7Fh.
* wahlweise die Adressen 00..07, 08..0Fh, 10..17h oder 18h..1Fh
sind als Register adressierbar.
Auf ein und dieselbe Speicherstelle kann so für einige Adressen
auf verschiedene Weise zugegriffen werden. Hinzu kommt noch, daß
auch der Stack im internen RAM angelegt wird. Dazu gibts ein SFR,
den Stack-Pointer (SP). Auf dem Stack werden bei einem Interrupt
oder Call die Return-Adressen abgelegt. Auch die Befehle PUSH und
POP wirken auf den Stack. Der SP wird bei jedem PUSH inkrementiert.
Wichtig: Nach einem Reset ist der SP mit der Adresse 07 geladen.
Der erste PUSH erfolgt so auf die Adresse 08. Verwendet das Pro-
gramm DATA-Variablen, so muß unbedingt der Stack auf eine Adres-
se oberhalb umgelegt werden.
Flags:
~~~~~~
┌────┬────┬────┬───┬───┬────┬───┬───┐ Das PSW hält nebenstehende
│ CY │ AC │ F0 │RS1│RS0│ OV │ x │ P │ Flags. Einige davon werden
└────┴────┴────┴───┴───┴────┴───┴───┘ bei der Befehlsabarbeitung
von der CPU gesetzt.
CY = Carry-Flag:
CY hält den Übertrag aus Bit 7 bei ADD, ADDC, SUBB, DA, RLC,
CY hält den Übertrag aus Bit 0 bei RRC,
CY ist Flag für Kleiner/größer bei CJNE
AC = Hilfs Carry:
AC hält den Übertrag aus Bit 3 bei ADD, ADDC, SUBB
P = Parität:
P = 1, wenn Anzahl der Bits in ACC ungerade
OV = Überlauf:
OV = 1, wenn Ergebnis bei MUL größer als 0FFh (WORD),
OV = 1, wenn Division durch 0 bei DIV
OV = 1, wenn Vorzeichen-Fehler bei ADD, ADDC, SUBB:
Beim Rechnen mit vorzeichenbehafteten Zahlen repräsentiert Bit 7
das Vorzeichen (1 = Minus). Werden zwei positive Zahlen addiert,
so muß das Ergebnis auch positiv sein. Die CPU addiert nur Hex-
Werte. Ein Übertrag in Bit 7, würde aber als negativ interpretiert.
Beispiel: 33h + 33h = 66h und OV = 0; 66h = 102 (dezimal)
66h + 66h = CCh und OV = 1; CCh = -76 (dezimal)
RS1:RS0 selektieren die aktive Registerbank. Nach dem Reset ist
PSW mit 00 geladen, damit werden als Register die Adressen 00..07
verwendet (deßhalb beginnt der Stack beim Reset erst bei 08).
Relative Sprünge:
~~~~~~~~~~~~~~~~~
Bei relativen Sprüngen wird zuerst der Befehls-Zeiger (IP) incre-
mentiert und anschließend wird dazu der im Opcode enthaltene rela-
tive Offset addiert. Vor der Addition erfolgt eine BYTE->WORD Kon-
vertierung des Offset-Wertes.
Der Offsetwert aus dem Opcode stellt dabei eine Zahl mit Vorzei-
chen dar, entsprechend ergibt die Konvertierung:
7Ah --> 007Ah hier +122 (dez)
B4h --> FFB4h hier -52 (dez)
Absolute Sprünge:
~~~~~~~~~~~~~~~~~
Bei absoluten Sprüngen und Calls wird zuerst der Befehls-Zeiger
(PC) incrementiert. Die Zieladresse wird danach gebildet, indem
die 5 höchsten Bits aus dem PC übernommen werden (PC AND 0F800h),
während die 11 niederwertigeren Bits aus dem Opcode gelesen werden.
Dazu wird das high Byte des Opcode um 5 Stellen nach rechts ge-
schiftet, das low Byte wird belassen. Dieser Wert wird logisch OR
mit dem PC verknüpft.
Zeit für Befehlsausführung:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Zur Ausführung vieler Befehle wird nur 1 CPU-Zyclus benötigt. Ei-
nige, insbesondes solche mit Zugriff auf externe Speicher, benöti-
gen 2 Zycluse. Ein Zyclus dauert 6 CPU-Takte (= 12 Quarztakte).
Bei 12 MHz dauert so 1 Zyclus 1 µs. In jedem Zyclus werden die Ti-
mer falls sie laufen jeweils um 1 incrementiert.
Stack:
~~~~~~
Der Stack liegt im internen RAM und wächst von unten nach oben.
Der SP zeigt auf den zuletzt gepushten Wert. Ist der SP größer 7Fh
beim 8051 (oder BFh beim 8044) so wird er bei einem PUSH weiterhin
incrementiert, aber bei einem POP kommt nur #0FFh zurück, der ge-
pushte Wert ist verloren. Wird der SP über 0FFh hinaus incremen-
tiert, so überschreibt der Stack die Adressen 00....
Bei Calls und Interrupts wird von der CPU die Returnadresse auf
den Stack gelegt (low Byte zuerst). Bei einem Interrupt wird nur
die Returnadress auf den Stack gesichert (nicht wie beim 8088 auch
die Flags).
allgemeine Bemerkungen zur Syntax:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Die meißten Assemblern erwarten bei der Eingabe von Zahlen einen
dezimalen Wert. Bei HEX-Zahlen ist ein h und bei Binär-Zahlen ein
b anzuhängen. Jede Zahl muß mit einer Ziffer zwischen 0 und 9 be-
ginnen. Bei HEX-Zahlen ist gegebenenfalls eine 0 voranzustellen.
# vor einer Zahl heißt, das es sich um einen konstanter Wert han-
delt. Alle anderen Zahlenwerte, ohne #, werden als Adressen an-
gesehen.
@ weißt auf eine indirekte Adressierung hin. (Inhalt jener Spei-
cherstelle, deren Adresse in der hinter @ stehenden Register
steht.
A steht für Akkumulator (= ACC, jedoch wird ein spezieller Opcode
erzeugt, wenn A anstelle von ACC verwendet wird)
C steht für Carry-Flag (= CY, jedoch wird ein spezieller Opcode
erzeugt, wenn C anstelle von CY verwendet wird)
DPTR = Datenpointer setzt sich zusammen aus DPH und DPL.
PC = Programm-Counter (zeigt auf den nächsten abzuarbeitenden Be-
fehl). Der PC ist kein SFR, er kann nicht per Software gele-
sen werden. Gewissermaßen stellt aber der LJMP einen Schreib-
Befehl in den PC dar.
verwendete Abkürzungen:
-----------------------
Ri (mit i = 0...1) --> verwendet, um anzudeuten, daß R0 oder R1
für diesen Befehl zulässig sind
Rn (mit n = 0...7) --> verwendet, um anzudeuten, daß R0 ... R7
für diesen Befehl zulässig sind.
data --> es ist eine direkt adressierbare Speicherstelle anzuge-
ben (internes RAM 00..7Fh oder SFR 80..FFh). Der Inhalt
dieser Speicherstelle wird für die Operation verwendet.
#wert --> der angegebene Wert wird für die Operation verwendet.
codeAdr --> Zieladresse bei Sprüngen, CALL's. Auch bei SJMP wird
immer die Zieladresse angeschrieben. Erst der Assem-
bler berechnet den Offset und trägt ihn in den Opcode
ein.